﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;

using BlueCMS.Core.Data.Query.Clauses;
using BlueCMS.Core.Data.Query.Generator;

namespace BlueCMS.Core.Data.Query
{
    public class SelectQuery
    {
        public bool Distinct { get; set; }
        public int Limit { get; set; }
        public int Offset { get; set; }

        public Dictionary<string, DbParameter> Parameters { get; private set; }

        SelectClause SelectClause { get; set; }
        FromClause FromClause { get; set; }
        WhereClause WhereClause { get; set; }
        GroupByClause GroupByClause { get; set; }
        HavingClause HavingClause { get; set; }
        OrderByClause OrderByClause { get; set; }

        public SelectQuery()
        {
            Limit = -1;
            Offset = 0;

            SelectClause = new SelectClause();
            FromClause = new FromClause();
            WhereClause = new WhereClause();
            GroupByClause = new GroupByClause();
            HavingClause = new HavingClause();
            OrderByClause = new OrderByClause();
            Parameters = new Dictionary<string, DbParameter>();
        }

        public ISelectClause Select
        {
            get { return SelectClause; }
        }

        public IFromClause From
        {
            get { return FromClause; }
        }

        public IWhereClause Where
        {
            get { return WhereClause; }
        }

        public IGroupByClause GroupBy
        {
            get { return GroupByClause; }
        }

        public IHavingClause Having
        {
            get { return HavingClause; }
        }

        public IOrderByClause OrderBy
        {
            get { return OrderByClause; }
        }

        public string Sql
        {
            get
            {
                return DataAccess.Instance.GetQueryGenerator().ProcessSelectQuery(SelectClause, FromClause, WhereClause, GroupByClause, HavingClause, OrderByClause, Distinct, Limit, Offset, Parameters);
            }
        }

        public override string ToString()
        {
            return Sql;
        }

        public T ExecuteObject<T>()
        {
            DbDataReader reader = DataAccess.Instance.ExecuteDataReader(Sql, Parameters.Values.ToArray());

            return DataHelpers.FillObject<T>(reader);
        }

        public T ExecuteScalar<T>()
        {
            return (T)DataAccess.Instance.ExecuteScalar(Sql, Parameters.Values.ToArray());
        }

        public IList<T> ExecuteCollection<T>()
        {
            DbDataReader reader = DataAccess.Instance.ExecuteDataReader(Sql, Parameters.Values.ToArray());

            return DataHelpers.FillCollection<T>(reader);
        }
    }
}
